﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace Tools.Debugging {
    public class Logger {
        private Logger ( ) { }

        protected static TextWriter output;
        public static TextWriter Output { get { return Logger.output; } }
        protected static Object sync = new Object( );
        static Logger ( ) {
            output = Console.Out;
            //output = System.IO.File.AppendText( "output.txt" );

            Debug( typeof( Logger ), " --- logging started" );

        }
        private static bool doprint ( ) {

            return true;//Thread.CurrentThread.ManagedThreadId == 11;
        }
        private static bool doprint ( Object o ) {
            if ( o.GetType( ).FullName.Contains( "ClientSide" ) ) {
                Console.ForegroundColor = ConsoleColor.Red;
            } else if ( o.GetType( ).FullName.Contains( "ServerSide" ) ) {
                Console.ForegroundColor = ConsoleColor.Green;
            } else {
                Console.ForegroundColor = ConsoleColor.Gray;
            }
            return
                true
                //||
                //Thread.CurrentThread.ManagedThreadId == 12
                //||
                //Thread.CurrentThread.ManagedThreadId == 15
                ;
        }

        public static void Debug ( object o, String format, params object[] objs ) {
            String message = String.Format( format, objs );
            Debug( o, message );
        }

        public static void Debug ( object o, String message ) {
            lock ( sync ) {
                if ( doprint( o ) ) {
                    Thread thread = Thread.CurrentThread;
                    String threadName = thread.Name + " I" + thread.ManagedThreadId;
                    Output.WriteLine( "{0}, {1}[{5}] ({3}:{4}) :: {2}", DateTime.Now.ToString( "mm:ss.fff" ), o.GetType( ).FullName, message, thread.Name, thread.ManagedThreadId, o.GetHashCode( ) );
                    Output.Flush( );
                }
            }
        }

        public static void Debug ( Type type, String format, params object[] objs ) {
            Debug( type, String.Format( format, objs ) );
        }

        public static void Debug ( Type type, String message ) {
            if ( doprint( ) ) {
                Console.ForegroundColor = ConsoleColor.Blue;
                Thread thread = Thread.CurrentThread;
                String threadName = thread.Name + " I" + thread.ManagedThreadId;

                Output.WriteLine( "{0}, {1}[static] ({3}:{4}) :: {2}", DateTime.Now.ToString( "mm:ss.fff" ), type.Name, message, thread.Name, thread.ManagedThreadId );
                Output.Flush( );
            }
        }


        public static void Created ( object o ) {
            Debug( o, "created" );
        }



        public static void Exception ( object o, string message, Exception e ) {
            Exception _e = e;

            Thread thread = Thread.CurrentThread;
            String threadName = thread.Name + " I" + thread.ManagedThreadId;
            Output.WriteLine( "{0}, {1}[{5}] ({3}:{4}) :: {2} : {6} \nmethod:{7}\ntrace\n{8}", DateTime.Now.ToString( "mm:ss.fff" ), o.GetType( ).Name, message, thread.Name, thread.ManagedThreadId, o.GetHashCode( ), e.Message, e.TargetSite.ToString( ), e.StackTrace );
            _e = _e.InnerException;
            while ( _e != null ) {
                Output.WriteLine( "--- Inner exception --------------------------------------------------------" );
                Output.WriteLine( "{0}, {1}[{5}] ({3}:{4}) :: {2} : {6} \nmethod:{7}\ntrace\n{8}", DateTime.Now.ToString( "mm:ss.fff" ), o.GetType( ).Name, message, thread.Name, thread.ManagedThreadId, o.GetHashCode( ), e.Message, e.TargetSite.ToString( ), e.StackTrace );
                _e = _e.InnerException;
            } ;
            Output.Flush( );
        }
    }
}
